/**
 * 
 * The MIT License
 * 
 * Copyright (c) 2008 the original author or authors.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:

 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.googlecode.gchartjava;

import static com.googlecode.gchartjava.ArraysUtil.asUnmodifiableList;
import static java.util.Collections.unmodifiableList;

import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

/**
 * XY line chart.
 * 
 * @see XYLine
 * @author Julien Chastang (julien.c.chastang at gmail dot com)
 */
public class XYLineChart extends AbstractPriorityChart {
	
	private static final String XY_LINE_CHART_URL = GCHART_URL + "?cht=lxy";
	
	private final List<XYLine> xylines;


	/**
	 * Create a XY line chart.
	 * 
	 * @param xylines
	 *            xy lines.
	 * @see XYLine
	 */
	public XYLineChart(final XYLine... xylines){
		super(asUnmodifiableList(xylines));
		this.xylines = asUnmodifiableList(xylines);
	}	

	/**
	 * Create a XY line chart.
	 * 
	 * @param xylines
	 *            xy lines.
	 * @see XYLine
	 */
	public XYLineChart(final List<? extends XYLine> xylines){
		super(unmodifiableList(xylines));
		this.xylines = unmodifiableList(xylines);
	}
			
 	/**
 	 *
 	 */
 	@Override
	protected void prepareLineData() {
		final List<Data> datas = new LinkedList<Data>();
		
		for (XYLine xyline : xylines) {
			final XYLine xy = removeDuplicatePoints(xyline);
			datas.add(xy.getXData());
			datas.add(xy.getYData());
		}
		setData(unmodifiableList(datas));
	}

	/**
	 * @param xyline
	 */
	private XYLine removeDuplicatePoints(final XYLine xyline) {
		final float[] xData = xyline.getXData().getData();
		final float[] yData = xyline.getYData().getData();
		
		// Removing duplicates. Can assume xData and yData are the same length.
		final Set<XYPoint> set = new LinkedHashSet<XYPoint>();
		for (int i = 0; i < xData.length; i++) {
			set.add(new XYPoint(xData[i], yData[i]));
		}
		
		final float[] x = new float[set.size()];
		final float[] y = new float[set.size()];
		
		int i = 0;
		for (XYPoint point : set) {
			x[i] = point.x;
			y[i] = point.y;
			i++;
		}
		return new XYLine(new Data(x), new Data(y));
	}

	/**
	 *
	 */
	@Override
	protected String getBaseURLString() {		
		return XY_LINE_CHART_URL;
	}
	
	/**
	 * 
	 */
	private static class XYPoint {
		private final float x;
		private final float y;

		/**
		 * 
		 */
		private XYPoint(final float x, final float y) {
			super();
			this.x = x;
			this.y = y;
		}

		/**
		 * 
		 */
		@Override
		public boolean equals(final Object obj) {
		    if (this == obj)
		      return true;
		    if (!(obj instanceof XYPoint))
		      return false;
		    final XYPoint objA = (XYPoint) obj;
		    return (this.x == objA.x) && (this.y == objA.y);
		}

		/**
		 * 
		 */
		@Override
		public int hashCode() {
			int hash = 1;
		    hash = hash * 31 + Float.valueOf(x).hashCode();
		    hash = hash * 31 + Float.valueOf(y).hashCode();
		    return hash;
		}
	}
}
